package com.cheng.tetris;

import com.cheng.tetris.Tetris.Tetris;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import static javax.swing.WindowConstants.EXIT_ON_CLOSE;

public class MainGame
        extends JPanel
{
    //游戏状态
    public static int state;

    public static final int READY = 0;
    public static final int GAMING = 1;
    public static final int END = 2;
    public static final int PAUSE = 3;

    //装下落完毕的方块的集合
    public static List<Rectangle> rectangles;

    //装下落中的方块的对象
    public static Tetris tetris;

    //装下一个来的方块的对象
    public static Tetris next;

    //装预计下落位置阴影的对象
    public static Tetris shadow;

    //全局随机数生成器
    public static Random random;

    //等级，越高越快
    public static int level;

    //分数
    public static int score;

    public static volatile MainGame mainGame;

    //睡眠变量，方块直接落到底应当等一小会再来下一个
    public static int sleep;

    //初始化
    public static void initialize()
    {
        rectangles = rectangles == null ? new ArrayList<>() : rectangles;//空就new

        rectangles.clear();//清空

        sleep = 0;
        score = 0;
        level = 1;

        random = new Random(System.currentTimeMillis());

        tetris = Tetris.getTetris(random.nextInt(7) + 1);
        next = Tetris.getTetris(random.nextInt(7) + 1);
        next.toShowNextPosition();
        shadow = null;


        state = READY;
    }

    public static void main(String[] args)
            throws InterruptedException
    {
        JFrame jFrame = new JFrame();
        jFrame.setVisible(true);
        jFrame.setBounds(0, 0, 518, 540);//设置大小
        jFrame.setDefaultCloseOperation(EXIT_ON_CLOSE);//设置窗口关闭方式为点叉关闭
        jFrame.setResizable(false);//设置窗口为不可改变大小

        mainGame = new MainGame();
        jFrame.add(mainGame);

        //添加鼠标监听器，点击后后如果准备始就开始，如果开始了就暂停，如果暂停了就开始，如果结束了就准备
        jFrame.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                super.mouseClicked(e);
                if (state == READY)
                {
                    try
                    {
                        initialize();
                        startGame();
                        state = GAMING;
                        mainGame.repaint();

                    }
                    catch (InterruptedException ex)
                    {
                        ex.printStackTrace();
                    }
                }
                else if (state == GAMING)
                {
                    state = PAUSE;
                    mainGame.repaint();
                }
                else if (state == PAUSE)
                {
                    state = GAMING;
                    synchronized (tetris)
                    {
                        tetris.notifyAll();
                        mainGame.repaint();
                    }
                }
                else if (state == END)
                {
                    state = READY;
                    mainGame.repaint();
                }
                shadow = tetris.getShadow(rectangles);
                mainGame.repaint();
            }
        });

        //添加键盘监听器
        jFrame.addKeyListener(new KeyHandler()
        {
            @Override
            public void noneRepetitiveKeyPressed(KeyEvent e)
            {
                if (state != GAMING)
                {
                    return;
                }
                synchronized (tetris)
                {
                    //空格旋转方块不要重复调用
                    if (e.getKeyCode() == KeyEvent.VK_UP)
                    {
                        tetris.turn(rectangles);
                        deleteHoleLine();
                    }
                    if (e.getKeyCode() == KeyEvent.VK_SPACE)
                    {
                        synchronized (rectangles)
                        {
                            tetris.moveBottom(rectangles);
                            sleep = 1000 - 100 * level;
                            System.out.println(sleep);
                        }
                    }
                }
                shadow = tetris.getShadow(rectangles);
                mainGame.repaint();
            }

/*            @Override
            public void repetitiveKeyPressed(KeyEvent e)
            {
                if (state != GAMING)
                {
                    return;
                }

            }*/

            @Override
            public void alwaysRepetitiveKePressed(KeyEvent e)
            {
                if (state != GAMING)
                {
                    return;
                }

                if (e.getKeyCode() == KeyEvent.VK_LEFT)
                {
                    tetris.moveLeft(rectangles);
                }
                else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
                {
                    tetris.moveRight(rectangles);
                }

                //点下就往下挪
                if (e.getKeyCode() == KeyEvent.VK_DOWN)
                {

                    tetrisMoveDown();

                    deleteHoleLine();
                }
                shadow = tetris.getShadow(rectangles);
                mainGame.repaint();
            }
        });


    }

    public static void startGame()
            throws InterruptedException
    {

        Thread thread = new Thread(new Runnable()
        {
            @Override
            public void run()
            {
/*                for (int i = 0; i < 10; i++)
                {
                    tetris.moveDown();
                }*/
                while (true)
                {
                    level = score / 200 + 1;
                    //循环一次等半秒
                    try
                    {
                        Thread.sleep(1000 - 100 * level);

                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    //暂停就wait，等待被唤醒
                    if (state == PAUSE)
                    {
                        synchronized (tetris)
                        {
                            try
                            {
                                tetris.wait();
                            }
                            catch (InterruptedException e)
                            {
                                e.printStackTrace();
                            }
                        }
                        continue;
                    }

                    tetrisMoveDown();
                    deleteHoleLine();
                    shadow = tetris.getShadow(rectangles);
                    if (isGameEnd())
                    {
                        state = END;
                        mainGame.repaint();
                        synchronized (tetris)
                        {
                            try
                            {
                                tetris.wait();
                            }
                            catch (InterruptedException e)
                            {
                                throw new RuntimeException(e);
                            }
                        }
                    }
                }
            }
        });
        thread.start();

    }

    public static void deleteHoleLine()
    {
        //从20行往上找，如果某一行块数等于10就重新
        int oneLineRectangles = 0;//用来计数一行出现的块数的变量
        int deleteLines = 0;
        synchronized (rectangles)
        {
            for (int i = 20; i > 0; i--)
            {
                oneLineRectangles = 0;
                for (Rectangle rectangle : rectangles)
                {
                    if (rectangle.getY() == i)
                    {
                        oneLineRectangles++;
                    }
                }
                if (oneLineRectangles >= 10)//如果够10个就全部删除
                {
                    deleteLines++;
                    Iterator<Rectangle> iterator = rectangles.iterator();
                    while (iterator.hasNext())
                    {
                        Rectangle rectangle = iterator.next();
                        if (rectangle.getY() == i)//如果是第i行的就全部删除
                        {
                            iterator.remove();
                        }
                        else if (rectangle.getY() < i)//如果是第i行上面的就全部向下移动
                        {
                            rectangle.setY(rectangle.getY() + 1);
                        }
                    }
                    i = 21;//全部删除后从头继续下一个判断，以免下来的行还能消除被跳过
                }
            }
        }
        switch (deleteLines)
        {
            case 1:
                score += 10;
                break;
            case 2:
                score += 30;
                break;
            case 3:
                score += 60;
                break;
            case 4:
                score += 100;
                break;
        }
        mainGame.repaint();
    }

    //无条件把tetris抄到rectangles里然后获取新的tetris
    public static void copyTetris()
    {
        synchronized (rectangles)
        {
            for (Rectangle rectangle : tetris.getRectangles())
            {
                rectangles.add(rectangle);
            }
        }
        next.resetPosition();
        tetris = next;
        next = Tetris.getTetris(random.nextInt(7) + 1);
        next.toShowNextPosition();
    }

    public static void tetrisMoveDown()
    {
        //如果向下落不下了就把这个块放到集合里
        if (!tetris.moveDown(rectangles))
        {
            copyTetris();
        }
        mainGame.repaint();
    }

    public static boolean isGameEnd()
    {
        synchronized (rectangles)
        {
            for (Rectangle rectangle : rectangles)
            {
                if (rectangle.getY() <= 0)
                {
                    System.out.println(rectangles);
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void paint(Graphics g)
    {
        super.paint(g);
        if (state == READY)
        {
            g.setFont(new Font("宋体", Font.BOLD, 40));
            g.setColor(Color.GREEN);
            g.drawString("俄罗斯方块", 145, 220);
            g.drawString("点击鼠标开始游戏", 80, 270);
            return;
        }
        else if (state == PAUSE)
        {
            g.setFont(new Font("宋体", Font.BOLD, 40));
            g.setColor(Color.GREEN);
            g.drawString("游戏暂停", 170, 250);
            return;
        }
        else if (state == END)
        {
            g.setFont(new Font("宋体", Font.BOLD, 40));
            g.setColor(Color.GREEN);
            g.drawString("游戏结束", 170, 250);
            g.drawString("您的得分是: " + score, 100, 300);
            return;
        }
        if (tetris == null)
        {
            return;
        }

        g.drawRect(0, 0, 200, 400);
        paintRectangles(g);
        paintShadow(g);
        paintTetris(g);
        paintScore(g);
        paintLevel(g);
        paintNext(g);
    }

    public void paintRectangles(Graphics graphics)
    {
        graphics.setColor(Color.BLACK);
        synchronized (rectangles)
        {
            //绘制已落下的块
            for (Rectangle rectangle : rectangles)
            {
                graphics.fillRect(rectangle.getAbsX() + 1, rectangle.getAbsY() + 1, 18, 18);
            }
        }
    }

    public void paintTetris(Graphics graphics)
    {
        graphics.setColor(Color.BLACK);
        synchronized (tetris)
        {
            //绘制下落中的方块
            for (Rectangle rectangle : tetris.getRectangles())
            {
                graphics.fillRect(rectangle.getAbsX() + 1, rectangle.getAbsY() + 1, 18, 18);
            }
        }
    }

    public void paintScore(Graphics graphics)
    {
        Font font = new Font("宋体", Font.BOLD, 40);
        graphics.setFont(font);
        graphics.drawString("得分: " + score, 210, 50);
    }

    public void paintLevel(Graphics graphics)
    {
        Font font = new Font("宋体", Font.BOLD, 40);
        graphics.setFont(font);
        graphics.drawString("等级: " + level, 210, 100);
    }

    public void paintShadow(Graphics graphics)
    {
        graphics.setColor(Color.GRAY);
        synchronized (shadow)
        {
            //绘制影子
            for (Rectangle rectangle : shadow.getRectangles())
            {
                graphics.fillRect(rectangle.getAbsX() + 1, rectangle.getAbsY() + 1, 18, 18);
            }
        }
    }

    public void paintNext(Graphics graphics)
    {
        synchronized (next)
        {
            //绘制下一块
            for (Rectangle rectangle : next.getRectangles())
            {
                graphics.fillRect(rectangle.getAbsX() + 1, rectangle.getAbsY() + 1, 18, 18);
            }
        }
    }

}
